package com.merry.beanFactory.bf;

import java.lang.annotation.Annotation;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 * BeanFactory的直接下级接口。
 *
 * 扩展了 {@link BeanFactory} 接口，为我们的容器提供了可以枚举所有bean实例的方法，而不是根据客户端的请求逐一尝试按名称查找bean。
 *      预加载所有bean定义的BeanFactory实现（如基于XML的工厂）可以实现此接口。
 *
 *  如果该实现类同时实现了 {@link HierarchicalBeanFactory} 接口，则返回值将不考虑任何BeanFactory层次结构，
 *      而仅与当前工厂中定义的bean相关。使用{@link BeanFactory Utils}辅助类来考虑祖先工厂中的bean。也就是说，枚举所有bean实例的方法，仅支持当前层级的容器。
 *
 */
public interface ListableBeanFactory extends BeanFactory {

    /**
     * 检查容器中是否有该beanName。
     */
    boolean containsBeanDefinition(String beanName);

    /**
     * 返回该容器中的beanDefinition的数量。
     */
    int getBeanDefinitionCount();

    /**
     * 获取该容器中所有的beanName数组。
     */
    String[] getBeanDefinitionNames();

    /**
     * 根据输入的类的类型返回所有匹配的beanName，（包括该类的子类）。
     */
    String[] getBeanNamesForType(ResolvableType type);

    /**
     * 返回与给定类型（包括子类）匹配的bean的名称
     */
    String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit);

    /**
     * 根据类型返回beanName数组，包括该类型的子类。
     */
    String[] getBeanNamesForType(@Nullable Class<?> type);

    /**
     * 同上
     */
    String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);

    /**
     * 根据类型，返回bean对象，封装成集合。
     */
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException;

    /**
     * 同上
     */
    <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
            throws BeansException;

    /**
     * 根据注解返回beanName数组。
     */
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);

    /**
     * 根据注解返回bean对象，并封装成集合。
     */
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;

    /**
     * 根据beanName和注解，返回这个bean上面的该注解。
     */
    @Nullable
    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
            throws NoSuchBeanDefinitionException;

}
